package com.hexacta.hrs.report.managers;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.vectrics.common.util.DateUtil;
import org.vectrics.employee.Employee;

import com.hexacta.hrs.domain.staffing.assignment.AvailabilityStatus;
import com.hexacta.hrs.domain.staffing.assignment.EmployeeAssignment;
import com.hexacta.hrs.report.dtos.ResourcesSummaryDetailsDTO;
import com.hexacta.hrs.services.employee.EmployeeService;
import com.hexacta.hrs.services.staffing.EmployeeAssignmentService;

/**
 * 
 * 
 * @author nscuri
 *
 */
public class PeopleStaffingSummaryReportImpl extends StaffingSummaryReport {

	public PeopleStaffingSummaryReportImpl(EmployeeService employeeService,
			EmployeeAssignmentService employeeAssignmentService,
			Map<String, String> reportTemplateMap, Date dateFrom, Date dateTo) {
		
		super(employeeService, employeeAssignmentService, reportTemplateMap, dateFrom,
				dateTo);
	}

	@Override
	protected void insertResourcesForEmployeeAssignments(
			ResourcesSummaryDetailsDTO resourcesDTO,
			List<EmployeeAssignment> filterAssignmentsForEmployeeBetweenDates,
			int month, int year, Employee employee) {
		
		boolean isUnassigned = true;
		double currentAmount = 0;
		
		for (EmployeeAssignment employeeAssignment: filterAssignmentsForEmployeeBetweenDates) {
			
			double amount = this.calculateAmountForDates(employeeAssignment, month, year);
			
			if (amount > 0 && employeeAssignment.getAvailabilityStatus().equals(AvailabilityStatus.Interno)) {
				resourcesDTO.increment(AvailabilityStatus.Interno, month, amount);
				currentAmount += amount;
				isUnassigned = false;
			}
			
			if (amount > 0 && employeeAssignment.getAvailabilityStatus().equals(AvailabilityStatus.AddOnAvailable)) {
				resourcesDTO.increment(AvailabilityStatus.AddOnAvailable, month, amount);
				currentAmount += amount; 
				isUnassigned = false;
			}
			
			if (amount > 0 && employeeAssignment.getAvailabilityStatus().equals(AvailabilityStatus.AddOnNotAvailable)) {
				resourcesDTO.increment(AvailabilityStatus.AddOnNotAvailable, month, amount);
				currentAmount += amount;
				isUnassigned = false;
			}
			
			if (amount > 0 && employeeAssignment.getAvailabilityStatus().equals(AvailabilityStatus.AsignadoCliente)) {
				resourcesDTO.increment(AvailabilityStatus.AsignadoCliente, month, amount);
				currentAmount += amount;
				isUnassigned = false;
			}
		}
		if (isUnassigned || currentAmount < 1) {
			resourcesDTO.increment(AvailabilityStatus.NoAsignado, month, 1.00 - currentAmount);
		}
		
	}

	private double calculateAmountForDates(
			EmployeeAssignment employeeAssignment, int month, int year) {
		Date assignmentStartDate = employeeAssignment.getStartDate().getTime();
		Date assignmentEndDate = employeeAssignment.getEndDate().getTime();
		
		Calendar startFound = Calendar.getInstance();
		Calendar endFound = Calendar.getInstance();
		
		startFound.set(year, month , 1);
		endFound.set(year, month, 1);
		endFound.set(year, month,endFound.getActualMaximum(Calendar.DAY_OF_MONTH));
		
		boolean includeStart = DateUtil.isBetween(startFound.getTime(), assignmentStartDate, assignmentEndDate);
		boolean includeEnd = DateUtil.isBetween(endFound.getTime(), assignmentStartDate, assignmentEndDate);
		
		if( includeStart && includeEnd ) {
			return Double.valueOf(1);
		}
		if ( includeStart && !includeEnd ) {
			double workingDays = DateUtil.getWorkingDaysBetween(startFound.getTime(), assignmentEndDate);
			return  Double.valueOf(workingDays/DateUtil.getWorkingDaysBetween(startFound.getTime(), endFound.getTime()));
		}
		if ( !includeStart && includeEnd ) {
			int workingDays = DateUtil.getWorkingDaysBetween(assignmentStartDate, endFound.getTime());
			return Double.valueOf(workingDays / DateUtil.getWorkingDaysBetween(startFound.getTime(), endFound.getTime()));
		}
		
		return 0;
	}

}
